package edu.stanford.bmir.protege.web.client.ui.ontology.stkos.mapper.option;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RadioButton;

import edu.stanford.bmir.protege.web.client.dispatch.DispatchServiceManager;
import edu.stanford.bmir.protege.web.client.project.Project;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.StkosUtilServiceManager;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.common.MatchLevel;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.mapper.CancelMapperResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.mapper.MappingOptions;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.mapper.MappingResult;
import edu.stanford.bmir.protege.web.client.rpc.stkosutil.mapper.actions.CancelMapperAction;
import edu.stanford.bmir.protege.web.client.ui.library.msgbox.MessageBox;
import edu.stanford.bmir.protege.web.client.ui.library.msgbox.YesNoHandler;
import edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.GWTExtUtil;
import edu.stanford.bmir.protege.web.client.ui.ontology.stkos.common.interfaces.StkosCallBack;
import edu.stanford.bmir.protege.web.client.ui.projectmanager.DownloadProjectRequestHandler;
import edu.stanford.bmir.protege.web.client.ui.projectmanager.DownloadProjectRequestHandlerImpl;
import edu.stanford.bmir.protege.web.shared.project.GetAvailableProjectsAction;
import edu.stanford.bmir.protege.web.shared.project.GetAvailableProjectsResult;
import edu.stanford.bmir.protege.web.shared.project.ProjectDetails;

public class StkosMapperOptionView extends Composite implements HasEnabled {

	public enum StkosMapperOptionViewButtonType {

		AUTOMATCH("自动匹配"),

		SHOWCLASSMAPPERRESULT("显示类映射结果"),

		SHOWPROPERTYMAPPERSULT("显示属性映射结果"),

		EXPORTRESULT("导出结果"),

		CANCEL("取消")

		;

		private String text;

		private StkosMapperOptionViewButtonType(String text) {
			this.text = text;
		}

		public String getButtonText() {
			return text;
		}
	}

	public enum StkosMapperOptionViewListBoxType {

		ACCORDINGONTOLOGY("参考本体")

		;

		private String text;

		private StkosMapperOptionViewListBoxType(String text) {
			this.text = text;
		}

		public String getButtonText() {
			return text;
		}
	}

	interface StkosMapperOptionViewUiBinder extends
			UiBinder<HTMLPanel, StkosMapperOptionView> {
	}

	private static StkosMapperOptionViewUiBinder ourUiBinder = GWT
			.create(StkosMapperOptionViewUiBinder.class);

	private Project project;

	private List<ProjectDetails> availableProjectDetails;

	private Map<StkosMapperOptionViewButtonType, StkosCallBack> btnHandlers = new HashMap<StkosMapperOptionViewButtonType, StkosCallBack>();

	private Map<StkosMapperOptionViewListBoxType, StkosCallBack> listBoxHandlers = new HashMap<StkosMapperOptionViewListBoxType, StkosCallBack>();

	/** 参考本体 */
	@UiField
	protected ListBox accordingOntologies;

	/** 精确匹配 */
	@UiField
	protected RadioButton exactMatching;
	/** 模糊匹配 */
	@UiField
	protected RadioButton fuzzyMatching;

	/** 自动匹配 */
	@UiField
	protected Button btnAutoMatch;
	/** 显示类映射结果 */
	@UiField
	protected Button btnShowClassMapperResult;
	/** 显示属性映射结果 */
	@UiField
	protected Button btnShowPropertyMapperResult;
	/** 导出结果 */
	@UiField
	protected Button btnExportResult;
	/** 取消 */
	@UiField
	protected Button btnCancel;

	public StkosMapperOptionView(Project project) {
		this.project = project;

		HTMLPanel rootElement = ourUiBinder.createAndBindUi(this);
		initWidget(rootElement);

		setAccordingOntologiesItems();
		registerBtnEventHandlers();
		registerListBoxChangeEventHandlers();
	}

	@Override
	protected void onDetach() {
		super.onDetach();
		btnHandlers.clear();
		listBoxHandlers.clear();
	}

	@Override
	public boolean isEnabled() {
		return true;
	}

	@Override
	public void setEnabled(boolean enabled) {
		btnAutoMatch.setEnabled(enabled);
		btnShowClassMapperResult.setEnabled(enabled);
		btnShowPropertyMapperResult.setEnabled(enabled);
		btnExportResult.setEnabled(enabled);
		btnCancel.setEnabled(enabled);
	}

	public MappingOptions getOptions() {
		MappingOptions options = new MappingOptions();
		if (exactMatching.getValue()) {
			options.setMatchLevel(MatchLevel.CASE_INSENSITIVE);
		}
		if (fuzzyMatching.getValue()) {
			options.setMatchLevel(MatchLevel.INCLUSIVE);
		}
		return options;
	}

	public ProjectDetails getSelectedProjectDetails() {
		ProjectDetails selectedPd = null;
		if (accordingOntologies.getSelectedIndex() != -1) {
			String selectedValue = accordingOntologies
					.getValue(accordingOntologies.getSelectedIndex());
			for (ProjectDetails pd : availableProjectDetails) {
				if (pd.getProjectId().getId().equals(selectedValue)) {
					selectedPd = pd;
					break;
				}
			}
		}
		return selectedPd;
	}

	protected void setAccordingOntologiesItems() {
		availableProjectDetails = null;
		accordingOntologies.clear();
		DispatchServiceManager.get().execute(new GetAvailableProjectsAction(),
				new AsyncCallback<GetAvailableProjectsResult>() {
					@Override
					public void onFailure(Throwable caught) {
						GWT.log("Loading project list error!", caught);
					}

					@Override
					public void onSuccess(GetAvailableProjectsResult result) {
						if (result == null || result.getDetails() == null
								|| result.getDetails().size() == 0) {
							GWT.log("Did not find any projects!");
						} else {
							availableProjectDetails = new ArrayList<ProjectDetails>();
							String pid = null;
							if (project != null
									&& project.getProjectId() != null) {
								pid = project.getProjectId().getId();
							}
							for (ProjectDetails pd : result.getDetails()) {
								try {
									if (!pd.isInTrash()
											&& !pd.getProjectId().getId()
													.equals(pid)) {
										availableProjectDetails.add(pd);
									}
								} catch (Exception e) {
								}
							}

							if (availableProjectDetails.size() > 0) {
								accordingOntologies.addItem("请选择本体",
										GWTExtUtil.DEFAULTLISTBOXITEMVALUEID);
								for (ProjectDetails pd : availableProjectDetails) {
									try {
										accordingOntologies.addItem(pd
												.getDisplayName(), pd
												.getProjectId().getId());
									} catch (Exception e) {
									}
								}
							}
						}
					}
				});
	}

	protected void registerListBoxChangeEventHandlers() {
		accordingOntologies.addChangeHandler(new ChangeHandler() {
			@Override
			public void onChange(ChangeEvent event) {
				btnCancel.setEnabled(false);

				if (listBoxHandlers
						.get(StkosMapperOptionViewListBoxType.ACCORDINGONTOLOGY) != null) {
					listBoxHandlers.get(
							StkosMapperOptionViewListBoxType.ACCORDINGONTOLOGY)
							.onCallBack(event);
				}
			}
		});
	}

	protected void registerBtnEventHandlers() {
		ClickHandler clickHandler = new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				if (event.getSource().equals(btnAutoMatch)) {
					autoMatch();
				} else if (event.getSource().equals(btnShowClassMapperResult)) {
					showClassMapperResult();
				} else if (event.getSource()
						.equals(btnShowPropertyMapperResult)) {
					showPropertyMapperResult();
				} else if (event.getSource().equals(btnExportResult)) {
					exportResult();
				} else if (event.getSource().equals(btnCancel)) {
					cancel();
				}
			}
		};
		btnAutoMatch.addClickHandler(clickHandler);
		btnShowClassMapperResult.addClickHandler(clickHandler);
		btnShowPropertyMapperResult.addClickHandler(clickHandler);
		btnExportResult.addClickHandler(clickHandler);
		btnCancel.addClickHandler(clickHandler);
	}

	protected void autoMatch() {
		ProjectDetails spd = getSelectedProjectDetails();
		if (spd == null) {
			MessageBox.showAlert("提示", "请选择一个参考本体!");
			return;
		}

		GWTExtUtil.showProgressMonitor("提示", "程序正在处理、请稍候...");

		String project1Name = project.getProjectId().getId();
		String project2Name = spd.getProjectId().getId();
		MappingOptions options = getOptions();
		AsyncCallback<MappingResult> callback = new AsyncCallback<MappingResult>() {
			@Override
			public void onFailure(Throwable caught) {
				GWT.log(this.toString() + ", AutoMatch error.", caught);
				callAutoMatchHandler(null);
			}

			@Override
			public void onSuccess(MappingResult result) {
				callAutoMatchHandler(result);
				btnCancel.setEnabled(true);
			}
		};
		StkosUtilServiceManager.getInstance().mapOntologies(project1Name,
				project2Name, options, callback);
	}

	protected void showClassMapperResult() {
		if (btnHandlers
				.get(StkosMapperOptionViewButtonType.SHOWCLASSMAPPERRESULT) != null) {
			btnHandlers.get(
					StkosMapperOptionViewButtonType.SHOWCLASSMAPPERRESULT)
					.onCallBack();
		}
	}

	protected void showPropertyMapperResult() {
		if (btnHandlers
				.get(StkosMapperOptionViewButtonType.SHOWPROPERTYMAPPERSULT) != null) {
			btnHandlers.get(
					StkosMapperOptionViewButtonType.SHOWPROPERTYMAPPERSULT)
					.onCallBack();
		}
	}

	protected void exportResult() {
		DownloadProjectRequestHandler downloadProjectRequestHandler = new DownloadProjectRequestHandlerImpl();
		downloadProjectRequestHandler.handleProjectDownloadRequest(project
				.getProjectId());
		doExportHandler();
	}

	protected void cancel() {
		final String projectName = project.getProjectId().getId();
		String refProjectName = null;
		try {
			refProjectName = getSelectedProjectDetails().getProjectId().getId();
		} catch (Exception e) {
		}
		final String rpn = refProjectName;
		YesNoHandler ynHandler = new YesNoHandler() {
			@Override
			public void handleYes() {
				cancelOperation(projectName, rpn);
			}

			@Override
			public void handleNo() {
			}
		};
		MessageBox.showYesNoConfirmBox("取消操作", "你确定要取消映射操作吗?", ynHandler);
	}

	protected void cancelOperation(String projectName, String refProjectName) {
		if (projectName == null || refProjectName == null) {
			MessageBox.showAlert("提示", "必要信息不完整,操作失败!");
			btnCancel.setEnabled(false);
			return;
		}

		GWTExtUtil.showProgressMonitor("提示", "程序正在处理、请稍候...");

		CancelMapperAction action = new CancelMapperAction();
		action.setRefProjectName(refProjectName);
		AsyncCallback<CancelMapperResult> callback = new AsyncCallback<CancelMapperResult>() {
			@Override
			public void onFailure(Throwable caught) {
				MessageBox.showAlert("取消操作", "取消操作处理失败、详情：" + caught);
				doCancelHandler(null);
			}

			@Override
			public void onSuccess(CancelMapperResult result) {
				doCancelHandler(result);
			}
		};
		StkosUtilServiceManager.getInstance().cancelMapper(projectName, action,
				callback);
	}

	protected void doCancelHandler(CancelMapperResult result) {
		GWTExtUtil.hideProgressMonitor("提示", "程序处理完成!", 1);

		if (result != null) {
			MessageBox.showMessage("取消映射操作成功", "共删除映射类" + result.getDelClass()
					+ "个,映射属性" + result.getDelProperty() + "个," + "个,映射个体"
					+ result.getDelIndividual() + "个!");
		} else {
			MessageBox.showAlert("取消映射操作结束", "返回结果为空!");
		}
		btnCancel.setEnabled(false);

		if (btnHandlers.get(StkosMapperOptionViewButtonType.CANCEL) != null) {
			btnHandlers.get(StkosMapperOptionViewButtonType.CANCEL).onCallBack(
					result);
		}
	}

	protected void doExportHandler() {
		if (btnHandlers.get(StkosMapperOptionViewButtonType.EXPORTRESULT) != null) {
			btnHandlers.get(StkosMapperOptionViewButtonType.EXPORTRESULT)
					.onCallBack();
		}
	}

	public void setBtnHandler(StkosMapperOptionViewButtonType type,
			StkosCallBack cb) {
		if (type == null || cb == null) {
			return;
		}
		btnHandlers.remove(type);
		btnHandlers.put(type, cb);
	}

	public void setListBoxHandler(StkosMapperOptionViewListBoxType type,
			StkosCallBack cb) {
		if (type == null || cb == null) {
			return;
		}
		listBoxHandlers.remove(type);
		listBoxHandlers.put(type, cb);
	}

	protected void callAutoMatchHandler(MappingResult mappingResult) {
		GWTExtUtil.hideProgressMonitor("提示", "程序处理完成!", 850);

		if (btnHandlers.get(StkosMapperOptionViewButtonType.AUTOMATCH) != null) {
			btnHandlers.get(StkosMapperOptionViewButtonType.AUTOMATCH)
					.onCallBack(mappingResult);
		}
	}
}
